﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace SalesSys.Comm.Utility
{
    public static class ReflectionEx
    {


        /// <summary>
        /// 通过方法名称及方法的参数类型名称查找方法，返回第一个查找到的.此方法主要用于查找泛型重载的方法,即方法名相同但泛型参数不同的多个方法过滤,不应用于复杂条件过滤
        /// </summary>
        /// <param name="ty"></param>
        /// <param name="name"></param>
        /// <param name="paramType">方法参数列表，使用其名称进行对比</param>
        /// <returns></returns>
        public static MethodInfo GetMethodByParamTypesName(this Type ty, string name, params Type[] paramType)
        {
            var memberList = ty.GetMember(name, MemberTypes.Method, BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance);
            var methodList = memberList.Cast<MethodInfo>();
            MethodInfo foundMothod = null;
            foreach (var member in memberList)
            {
                var method = member as MethodInfo;
                var pTypes = method.GetParameters();
                if (pTypes.Length != paramType.Length)
                    continue;
                bool isFound = true;
                for (int i = 0; i < pTypes.Length; i++)
                {
                    if (pTypes[i].ParameterType.Name != paramType[i].Name)
                    {
                        isFound = false;
                        break;
                    }
                }
                if (isFound)
                {
                    foundMothod = method;
                    break;
                }
            }
            return foundMothod;
        }



        /// <summary>
        /// 移除指定名称事件的所有订阅
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="c"></param>
        /// <param name="name"></param>
        static void RemoveAllEventHandler<T>(T c, string name)
        {
            Delegate[] invokeList = GetObjectEventList(c, name);
            if (invokeList == null)
                return;
            foreach (Delegate del in invokeList)
            {
                typeof(T).GetEvent(name).RemoveEventHandler(c, del);
            }
        }
        /// <summary>
        /// 移除指定名称事件的所有订阅
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="c"></param>
        /// <param name="name"></param>
        static void RemoveAllEventHandler(object c, string name)
        {
            Delegate[] invokeList = GetObjectEventList(c, name);
            if (invokeList == null)
                return;
            foreach (Delegate del in invokeList)
            {
                c.GetType().GetEvent(name).RemoveEventHandler(c, del);
            }
        }
        /// <summary>
        /// 反射查找事件订阅列表
        /// </summary>
        /// <param name="p_Object"></param>
        /// <param name="p_EventName"></param>
        /// <returns></returns>
        public static Delegate[] GetObjectEventList(this object p_Object, string p_EventName)
        {
            // Get event field
            FieldInfo _Field = p_Object.GetType().GetField(p_EventName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static);
            if (_Field == null)
            {
                return null;
            }
            // get the value of event field which should be a delegate
            object _FieldValue = _Field.GetValue(p_Object);

            // if it is a delegate
            if (_FieldValue != null && _FieldValue is Delegate)
            {
                // cast the value to a delegate
                Delegate _ObjectDelegate = (Delegate)_FieldValue;
                // get the invocation list
                return _ObjectDelegate.GetInvocationList();
            }
            return null;
        }

        /// <summary>
        /// 获取指定属性信息
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="select"></param>
        /// <returns></returns>
        public static PropertyInfo GetPropertyInfo<T,R>(Expression<Func<T, R>> select)
        {
            var body = select.Body;
            if (body.NodeType == ExpressionType.Convert)
            {
                var o = (body as UnaryExpression).Operand;
                return (o as MemberExpression).Member as PropertyInfo;
            }
            else if (body.NodeType == ExpressionType.MemberAccess)
            {
                return (body as MemberExpression).Member as PropertyInfo;
            }
            return null;
        }

        /// <summary>
        /// 获取指定类型中属性的特性
        /// </summary>
        /// <typeparam name="TAttr">要获取的特性</typeparam>
        /// <param name="classType">类型</param>
        /// <param name="flags">查找范围</param>
        /// <returns></returns>
        public static Dictionary<FieldInfo, TAttr> GetTypeFieldSingleAttr<TAttr>(Type classType, BindingFlags flags = BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public) where TAttr : Attribute
        {
            var dic = new Dictionary<FieldInfo, TAttr>();
            var fields = classType.GetFields(flags);
            foreach (var item in fields)
            {
                var attrs = item.GetCustomAttributes<TAttr>();
                if (attrs == null || attrs.Count() < 1)
                    continue;
                var attr = attrs.First();
                dic.Add(item, attr);
            }
            return dic;
        }

    }
   
}
